package com.boarsoft.sofa.filter;

import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.RejectedExecutionException;

import com.alipay.sofa.rpc.core.exception.RpcErrorType;
import com.alipay.sofa.rpc.core.exception.SofaRpcException;
import com.alipay.sofa.rpc.core.request.SofaRequest;
import com.alipay.sofa.rpc.core.response.SofaResponse;
import com.alipay.sofa.rpc.ext.Extension;
import com.alipay.sofa.rpc.filter.AutoActive;
import com.alipay.sofa.rpc.filter.Filter;
import com.alipay.sofa.rpc.filter.FilterInvoker;
import com.boarsoft.common.util.ReflectUtil;
import com.boarsoft.rpc.core.RpcContext;
import com.boarsoft.rpc.core.RpcCore;
import com.boarsoft.rpc.mock.RpcApiConfig;
import com.boarsoft.soagov.config.SvcConfig;
import com.boarsoft.soagov.spy.SpyData;
import com.boarsoft.soagov.spy.SvcSpy;
import com.boarsoft.sofa.SofaAdapter;

/**
 * 用于正常的SOFA RPC调用的拦截（包括RemoteHandler的正常调用）
 *
 * @author Mac_J
 *
 */
@Extension("autoMockFilter")
@AutoActive(providerSide = true, consumerSide = true)
public class AutoMockFilter extends Filter {
	@Override
	public boolean needToLoad(FilterInvoker invoker) {
		// 判断一些条件，自己决定是否加载这个 Filter。
		return true;
	}

	@Override
	public SofaResponse invoke(FilterInvoker invoker, SofaRequest request) throws SofaRpcException {
		Object mocker = invoker.getConfig().getMockRef();
		String key = ReflectUtil.getMethodSign(request.getMethod());
		RpcContext rpcContext = RpcCore.getCurrentInstance().getRpcContext();
		SvcSpy svcSpy = rpcContext.getSvcSpy();
		if (svcSpy == null) {
			if (RpcApiConfig.isMocking(key)) {
				try {
					return SofaAdapter.mock(key, request, mocker);
				} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
					throw new SofaRpcException(RpcErrorType.CLIENT_FILTER, e);
				}
			}
		} else {
			SpyData sd = svcSpy.getSpyData(key);
			int status = svcSpy.checkStatus(sd);
			// 检查服务的开关状态，与是否开启了结果模拟
			if (status == SvcConfig.STATUS_DISABLE) {
				// 如果服务被关闭，直接抛出拒绝执行异常
				throw new RejectedExecutionException(key);
			} else if (status == SvcConfig.STATUS_MOCKING) {
				// 如果开启了结果模拟功能，通过服务治理插件调用模拟器，返回模拟的结果
				try {
					return SofaAdapter.mock(key, request, mocker);
				} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
					throw new SofaRpcException(RpcErrorType.CLIENT_FILTER, e);
				}
			}
		}
		request.addRequestProp("mock", RpcApiConfig.isMocking(key));
		return invoker.invoke(request);
	}

}